/**
 * 全局WebSocket管理器
 * 单例模式，确保整个应用只有一个WebSocket连接
 */
class GlobalWebSocket {
  constructor() {
    this.ws = null;
    this.isConnected = false;
    this.isManuallyClosed = false;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
    this.reconnectDelayMs = 2000;
    this.heartbeatTimer = null;
    this.heartbeatIntervalMs = 20000;
    this.reconnectTimer = null;
    this.listeners = new Map(); // 存储事件监听器
    this.url = "wss://box.jingkakeji.com/ws/";
  }

  /**
   * 获取单例实例
   */
  static getInstance() {
    if (!GlobalWebSocket.instance) {
      GlobalWebSocket.instance = new GlobalWebSocket();
    }
    return GlobalWebSocket.instance;
  }

  /**
   * 初始化WebSocket连接
   */
  init() {
    if (this.isConnected || this.ws) {
      console.log("WebSocket已连接，无需重复初始化");
      return;
    }

    this.isManuallyClosed = false;
    this.clearReconnect();

    // #ifdef H5
    this.ws = new WebSocket(this.url);
    this.ws.onopen = (e) => {
      console.log("全局WebSocket连接成功", e);
      this.isConnected = true;
      this.reconnectAttempts = 0;
      this.startHeartbeat();
      this.emit("open", e);
    };

    this.ws.onclose = (e) => {
      console.log("全局WebSocket关闭", e);
      this.isConnected = false;
      this.stopHeartbeat();
      this.emit("close", e);
      if (!this.isManuallyClosed) {
        this.scheduleReconnect();
      }
    };

    this.ws.onmessage = (e) => {
      console.log("全局WebSocket收到消息:", e);
      this.emit("message", e);
    };

    this.ws.onerror = (e) => {
      console.log("全局WebSocket错误", e);
      this.stopHeartbeat();
      this.emit("error", e);
    };
    // #endif

    // #ifdef APP-PLUS
    this.ws = uni.connectSocket({
      url: this.url,
    });

    uni.onSocketOpen((e) => {
      console.log("全局WebSocket连接成功", e);
      this.isConnected = true;
      this.reconnectAttempts = 0;
      this.startHeartbeat();
      this.emit("open", e);
    });

    uni.onSocketClose((e) => {
      console.log("全局WebSocket关闭", e);
      this.isConnected = false;
      this.stopHeartbeat();
      this.emit("close", e);
      if (!this.isManuallyClosed) {
        this.scheduleReconnect();
      }
    });

    uni.onSocketMessage((e) => {
      console.log("全局WebSocket收到消息:", e);
      this.emit("message", e);
    });

    uni.onSocketError((e) => {
      console.log("全局WebSocket错误", e);
      this.stopHeartbeat();
      this.emit("error", e);
    });
    // #endif
  }

  /**
   * 开始心跳
   */
  startHeartbeat() {
    this.stopHeartbeat();
    this.heartbeatTimer = setInterval(() => {
      const payload = "ping";
      // #ifdef H5
      try {
        this.ws && this.ws.readyState === 1 && this.ws.send(payload);
      } catch (e) {
        console.error("发送心跳失败:", e);
      }
      // #endif
      // #ifdef APP-PLUS
      try {
        this.ws &&
          this.ws.send({
            data: payload,
          });
      } catch (e) {
        console.error("发送心跳失败:", e);
      }
      // #endif
    }, this.heartbeatIntervalMs);
  }

  /**
   * 停止心跳
   */
  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  /**
   * 安排重连
   */
  scheduleReconnect() {
    if (
      this.reconnectTimer ||
      this.reconnectAttempts >= this.maxReconnectAttempts
    ) {
      return;
    }
    const delay = this.reconnectDelayMs * Math.pow(2, this.reconnectAttempts);
    this.reconnectAttempts += 1;
    this.reconnectTimer = setTimeout(() => {
      this.reconnectTimer = null;
      console.log(
        `WebSocket重连尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts}`
      );
      this.init();
    }, delay);
  }

  /**
   * 清除重连定时器
   */
  clearReconnect() {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
  }

  /**
   * 关闭WebSocket连接
   */
  close(manual = false) {
    this.isManuallyClosed = !!manual;
    this.stopHeartbeat();
    this.clearReconnect();

    // #ifdef H5
    try {
      this.ws && this.ws.close();
    } catch (e) {
      console.error("关闭WebSocket失败:", e);
    }
    // #endif

    // #ifdef APP-PLUS
    try {
      uni.closeSocket({
        code: 1000,
        reason: "manual close",
      });
    } catch (e) {
      console.error("关闭WebSocket失败:", e);
    }
    // #endif

    this.ws = null;
    this.isConnected = false;
  }

  /**
   * 添加事件监听器
   */
  on(event, callback) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(callback);
  }

  /**
   * 移除事件监听器
   */
  off(event, callback) {
    if (!this.listeners.has(event)) return;
    const callbacks = this.listeners.get(event);
    const index = callbacks.indexOf(callback);
    if (index > -1) {
      callbacks.splice(index, 1);
    }
  }

  /**
   * 触发事件
   */
  emit(event, data) {
    if (!this.listeners.has(event)) return;
    const callbacks = this.listeners.get(event);
    callbacks.forEach((callback) => {
      try {
        callback(data);
      } catch (e) {
        console.error("事件回调执行失败:", e);
      }
    });
  }

  /**
   * 发送WebSocket消息
   */
  send(message) {
    if (!this.isConnected || !this.ws) {
      console.warn("WebSocket未连接，无法发送消息");
      return false;
    }

    try {
      // #ifdef H5
      if (this.ws.readyState === 1) {
        this.ws.send(message);
        return true;
      }
      // #endif

      // #ifdef APP-PLUS
      this.ws.send({
        data: message,
      });
      return true;
      // #endif
    } catch (e) {
      console.error("发送WebSocket消息失败:", e);
      return false;
    }
  }

  /**
   * 获取连接状态
   */
  getConnectionStatus() {
    return {
      isConnected: this.isConnected,
      isManuallyClosed: this.isManuallyClosed,
      reconnectAttempts: this.reconnectAttempts,
    };
  }
}

// 导出单例实例
export default GlobalWebSocket.getInstance();
